
#include "buffer.h"

/**
 * buf_push() pushes new data into the network input buffer
 * @param data
 * @param datalen
 */

bool buffer::buf_push(char *data, int datalen)
{
    int pos = 0;
    while (pos < datalen)
    {
        buf_t *b;
        if (!buf.size() || (buf.back().ilen == buf.back().flen))
        {
            if ((unsigned char)data[0] != 0xFF)
                return false;
            buf_t newbuf;
            newbuf.ilen = 0;
            newbuf.flen = *(int*)(data + pos + 2);
            newbuf.id = (unsigned char)data[1];
            newbuf.data = new char[newbuf.flen];
            newbuf.ison = false;
            b = &newbuf;
        }
        else
            b = &(buf.back());

        if ((b->flen - b->ilen) > (datalen - pos))
        {
            memcpy(b->data + b->ilen, data + pos, datalen - pos);
            b->ilen += datalen - pos;
            pos = datalen;
        }
        else
        {
            memcpy(b->data + b->ilen, data + pos, b->flen - b->ilen);
            pos += b->flen - b->ilen;
            b->ilen = b->flen;
        }
        
        if (!b->ison)
        {
            b->ison = true;
            buf.push(*b);
        }
    }
    return true;
}

/**
 * buf_get() retrieves first network packet in queue
 * @param id
 * @return packet
 */

char *buffer::buf_get(unsigned char *id)
{
    buf_t *b = &(buf.front());
    *id = b->id;
    return b->data + 6;
}

/**
 * buf_ready() tells the parser if there is an available packet to be read
 * @return true for ready
 * @return false for not ready
 */

bool buffer::buf_ready()
{
    if (buf.size())
        return (buf.front().ilen == buf.front().flen);
    return false;
}

/**
 * buf_pop() deletes the first packet in queue
 */

void buffer::buf_pop()
{
    delete [] buf.front().data;
    buf.pop();
}

